package com.wootion.cims.module.communityresidence.occupancy.service.impl;

import com.alibaba.excel.EasyExcel;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.extension.plugins.pagination.PageDTO;
import com.wootion.cims.dao.*;
import com.wootion.cims.general.utils.GetIp;
import com.wootion.cims.module.communitypersonal.model.Person;
import com.wootion.cims.module.communityresidence.occupancy.dto.OccupancyDto;
import com.wootion.cims.module.communityresidence.occupancy.dto.PageQueryOcc;
import com.wootion.cims.module.communityresidence.occupancy.excel.ExcelRules;
import com.wootion.cims.module.communityresidence.occupancy.service.OccupancyService;
import com.wootion.cims.module.communityresidence.residencelist.model.Residence;
import com.wootion.cims.module.systemsetting.community.model.SysCommunity;
import com.wootion.cims.module.systemsetting.log.model.SysLog;
import com.wootion.cims.module.systemsetting.polt.model.SysPlot;
import com.wootion.cims.module.systemsetting.user.model.SysUserRole;
import com.wootion.cims.module.systemsetting.user.model.User;
import com.wootion.cims.response.ResponseResult;
import com.wootion.cims.response.ResultCode;
import com.wootion.cims.shiro.utils.ShiroUtils;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.StringUtils;

import javax.annotation.Resource;
import javax.servlet.ServletOutputStream;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.File;
import java.io.FileInputStream;
import java.net.URLEncoder;
import java.text.SimpleDateFormat;
import java.util.*;

/**
 * @Author: LanQiang
 * @Date: 2022/12/19/9:55
 * @Description: 作用xxx
 */
@Service
@Slf4j
public class OccupancyServiceImpl implements OccupancyService {
    @Resource
    private SysUserRoleDao sysUserRoleDao;
    @Resource
    private SysRoleDao sysRoleDao;
    @Resource
    private SysUserCommunityDao sysUserCommunityDao;
    @Resource
    private ResidenceDao residenceDao;
    @Resource
    private PersonDao personDao;
    @Value("${cims.path}")
    private String basePath;
    @Resource
    private SysLogDao sysLogDao;
    @Resource
    private SysCommunityDao sysCommunityDao;
    @Resource
    private SysPlotDao sysPlotDao;
    /**
     * 列表查询
     * @param pageQueryOcc
     * @return
     */
    @Override
    public ResponseResult list(PageQueryOcc pageQueryOcc) {
        ExcelRules excelRules = pageQueryOcc.getCondition();
        Integer page = pageQueryOcc.getPage();
        Integer limit = pageQueryOcc.getLimit();
        if(Objects.isNull(page) || Objects.isNull(limit)){
            return ResponseResult.builder().code(ResultCode.SYSTEM_ERROR.getCode()).message("页码数和每页显得的天数不能为空").build();
        }
        //符合条件的住宅id
        List<String> resids = new ArrayList<>();
        //拿到所有符合入住人数范围房屋id
        List<Map<String,Object>> maps = new ArrayList<>();
        if(excelRules != null && excelRules.getMinNumber()!=null && excelRules.getMaxNumber() != null){
            if(excelRules.getMinNumber() == 0){
                List<Map<String, Object>> maps1 = residenceDao.countAbodeIdIsNull();
                for (Map<String, Object> map : maps1) {
                    String abodeId = (String) map.get("abode_id");
                    if(!StringUtils.hasText(abodeId)){//拿到全部为空的住宅id
                        String id = (String) map.get("id");
                        resids.add(id);
                    }
                }
            }
            //先查询符合条件的房屋id,以及统计当前房屋中的人数
            maps = residenceDao.countNumberPersonAbode(excelRules.getMinNumber(), excelRules.getMaxNumber());
            if(maps.size()<=0){
                PageDTO<OccupancyDto> dtoPageDTO = new PageDTO<>();
                dtoPageDTO.setCurrent(page);
                dtoPageDTO.setSize(limit);
                return ResponseResult.builder().data(dtoPageDTO).build();
            }
            for (Map<String, Object> map : maps) {
                String id = (String) map.get("id");
                resids.add(id);
            }
        }
        //特殊处理楼房的详细地址
        String newDetailedAddress = null;
        if(excelRules != null && excelRules.getDetailedAddress() != null){
            if(excelRules.getDetailedAddress().size()>1){
                List<String> detailedAddress = excelRules.getDetailedAddress();
                newDetailedAddress  =  detailedAddress.get(0) +"/"+ detailedAddress.get(1);
            }else{
                List<String> detailedAddress = excelRules.getDetailedAddress();
                newDetailedAddress = detailedAddress.get(0);
            }
        }
        String residenceClasses = null;
        String residenceCategory = null;
        String communityId = null;
        String plotId = null;
        String detailedAddress = null;
        String houseNumber = null;
        String keyWord = null;
        assert excelRules != null;
        residenceClasses = excelRules.getResidenceClasses();//住宅类别
        residenceCategory = excelRules.getResidenceCategory();//房屋类别
        communityId = excelRules.getCommunityId();//社区id
        plotId = excelRules.getPlotId();//小区id
        detailedAddress = newDetailedAddress;//详细地址
        houseNumber = excelRules.getHouseNumber();//门牌号
        keyWord = excelRules.getKeyWord();
        //获取当前登陆人的信息
        User user = (User) ShiroUtils.getSubject().getPrincipal();
        LambdaQueryWrapper<SysUserRole> lambdaQueryWrapper5 = new LambdaQueryWrapper<>();
        lambdaQueryWrapper5.eq(SysUserRole::getUserId, user.getId());
        SysUserRole sysUserRole = sysUserRoleDao.selectOne(lambdaQueryWrapper5);
        String roleKey = sysRoleDao.findByRoles(sysUserRole.getRoleId());
        PageDTO<OccupancyDto> dtoPageDTO;
        //街道管理员的情况下
        if("street:admin".equals(roleKey)){
            PageDTO<OccupancyDto> pageDTO = new PageDTO<>(page, limit);
            dtoPageDTO = residenceDao.findList(pageDTO, null, resids,keyWord, residenceClasses, residenceCategory, communityId, plotId, detailedAddress, houseNumber);
        }else{
            //如果是社区管理员
            List<String> commnityIds = sysUserCommunityDao.commnityIds(user.getId());
            if (Objects.isNull(commnityIds) || commnityIds.size() <= 0) {
                return ResponseResult.builder().message("当前用户还没有任何社区权限").build();
            }
            PageDTO<OccupancyDto> pageDTO = new PageDTO<>(page, limit);
            dtoPageDTO = residenceDao.findList(pageDTO, commnityIds, resids,keyWord, residenceClasses, residenceCategory, communityId, plotId, detailedAddress, houseNumber);
        }
        //开始处理入住人员姓名和入住人数还有业主信息
        List<OccupancyDto> records = dtoPageDTO.getRecords();
        log.info(records.size() + "");
        for (OccupancyDto record : records) {
            //处理业主姓名
            if(StringUtils.hasText(record.getOwnerId())){
                LambdaQueryWrapper<Person> lambdaQueryWrapper1 = new LambdaQueryWrapper<>();
                lambdaQueryWrapper1.eq(Person::getId,record.getOwnerId());
                lambdaQueryWrapper1.eq(Person::getEnabled,true);
                Person person = personDao.selectOne(lambdaQueryWrapper1);
                if(Objects.isNull(person)){
                    record.setPersonName(null);//业主姓名
                }else {
                    record.setPersonName(person.getName());//业主姓名
                }
            }else{
                record.setPersonName(null);
            }
            LambdaQueryWrapper<Person> lambdaQueryWrapper = new LambdaQueryWrapper<>();
            lambdaQueryWrapper.eq(Person::getAbodeId, record.getId());//房屋下的入住人员
            lambdaQueryWrapper.eq(Person::getEnabled,true);
            //处理入住人员姓名
            List<Person> peoples = personDao.selectList(lambdaQueryWrapper);
            List<String> names = new ArrayList<>();
            if (!Objects.isNull(peoples) && peoples.size() > 0) {
                for (Person people : peoples) {
                    names.add(people.getName());
                }
                record.setStayPersons(names);
                record.setStayPersonNumber((long) record.getStayPersons().size());//入住人员数
            } else {
                record.setStayPersons(null);
                record.setStayPersonNumber(0L);
            }
        }
        return ResponseResult.builder().data(dtoPageDTO).build();
    }

    /**
     * 根据房屋id,查询当前业主以及关联的所有入住人员(包括业主自身)信息
     * @param id
     * @return
     */
    @Override
    public ResponseResult find(String id) {
        //拿到房屋信息
        LambdaQueryWrapper<Residence> lambdaQueryWrapper = new LambdaQueryWrapper<>();
        lambdaQueryWrapper.eq(Residence::getId, id);
        lambdaQueryWrapper.eq(Residence::getEnabled, true);
        Residence residence = residenceDao.selectOne(lambdaQueryWrapper);
        //根据房屋信息，获取入住人员和户主的信息
        LambdaQueryWrapper<Person> lambdaQueryWrapper2 = new LambdaQueryWrapper<>();
        lambdaQueryWrapper2.eq(Person::getEnabled,true);
        lambdaQueryWrapper2.eq(Person::getAbodeId,residence.getId());
        List<Person> people = personDao.selectList(lambdaQueryWrapper2);
        for (Person person : people) {
            if(StringUtils.hasText(person.getAbodeId()) && person.getAbodeId().equals(id) && person.getId().equals(residence.getOwnerId())){
                person.setLivehold("业主自住");
                personDao.updateLivehold(person);
            }
        }
        List<Person> personList = new ArrayList<>(people);//入住人员
        return ResponseResult.builder().data(personList).build();
    }

    /**
     * 修改入住情况
     * @return
     */
    @Override
    @Transactional
    public ResponseResult updateSave(OccupancyDto occupancyDto, HttpServletRequest request) {
        String id = occupancyDto.getId();//获取住宅id
        int rows = 0;
        SysLog sysLog = new SysLog();
        StringBuilder stringBuilder = new StringBuilder();
        Residence residence = residenceDao.selectById(id);
        if (StringUtils.hasText(id)) {
            //此处备注不应该是住宅备注,而是入住情况的备注
            residenceDao.updateCheckRemark(id, occupancyDto.getCheckRemark());

            String checkRemark = occupancyDto.getCheckRemark();
            if(StringUtils.hasText(residence.getCheckRemark())){
                if(StringUtils.hasText(checkRemark)){
                    if(!checkRemark.equals(residence.getCheckRemark())){
                        stringBuilder.append("房屋入住备注，修改前:").append(residence.getCheckRemark()).append(",修改后:").append(checkRemark).append(".");
                    }
                }else {
                    stringBuilder.append("房屋入住备注，修改前:").append(residence.getCheckRemark()).append(",修改后:无").append(".");
                }
            }else {
                if(StringUtils.hasText(checkRemark)){
                    stringBuilder.append("房屋入住备注，修改前:无").append(",修改后:").append(checkRemark).append(".");
                }
            }
            rows++;
        }

        List<Person> personList = occupancyDto.getPersonList();
        if (personList != null && personList.size() > 0) {
            for (Person person : personList) {
                if(Objects.isNull(person)){
                    return ResponseResult.builder().code(ResultCode.SYSTEM_ERROR.getCode()).message(ResultCode.SYSTEM_ERROR.getMessage()).build();
                }
                Person person1 = personDao.selectById(person.getId());

                int i = personDao.updateById(person);
                if(i>0){
                    rows++;
                }
                Person person2 = personDao.selectById(person.getId());

                if (StringUtils.hasText(person1.getLivehold())){
                    if(StringUtils.hasText(person2.getLivehold())){
                        if(!person1.getLivehold().equals(person2.getLivehold())){
                            stringBuilder.append("居住性质，修改前:").append(person1.getLivehold()).append(",修改后:").append(person2.getLivehold()).append(".");
                        }
                    }else {
                        stringBuilder.append("居住性质，修改前:").append(person1.getLivehold()).append(",修改后:无").append(".");
                    }
                }else {
                    if(StringUtils.hasText(person2.getLivehold())){
                        stringBuilder.append("居住性质，修改前:无").append(",修改后:").append(person2.getLivehold()).append(".");
                    }
                }
                if (StringUtils.hasText(person1.getLiveremark())){
                    if(StringUtils.hasText(person2.getLiveremark())){
                        if(!person1.getLiveremark().equals(person2.getLiveremark())){
                            stringBuilder.append("入住人员备注，修改前:").append(person1.getLiveremark()).append(",修改后:").append(person2.getLiveremark()).append(".");
                        }
                    }else {
                        stringBuilder.append("入住人员备注，修改前:").append(person1.getLiveremark()).append(",修改后:无").append(".");
                    }
                }else {
                    if(StringUtils.hasText(person2.getLiveremark())){
                        stringBuilder.append("入住人员备注，修改前:无").append(",修改后:").append(person2.getLiveremark()).append(".");
                    }
                }
            }
            sysLog.setDetails(stringBuilder.toString());
        }
        sysLog.setIncident("入住信息");
        sysLog.setType("修改");
        sysLog.setValue("业务日志");
        sysLog.setCreateTime(new Date());
        sysLog.setIp(GetIp.getIpAddr(request));
        User user2 = (User) ShiroUtils.getSubject().getPrincipal();
        sysLog.setOperator(user2.getUsername());
        StringBuilder Builder = new StringBuilder();
        SysCommunity sysCommunity = sysCommunityDao.selectById(residence.getCommunityId());
        Builder.append(sysCommunity.getName());
        SysPlot sysPlot1 = sysPlotDao.selectById(residence.getPlotId());
        Builder.append(sysPlot1.getName()).append(residence.getAddress()).append(residence.getHouseNumber());
        sysLog.setContent("房屋地址:"+Builder);
        if(rows > 0){
            sysLog.setResult("成功");
        }else{
            sysLog.setResult("失败");
        }
        int insert = sysLogDao.insert(sysLog);
        if (insert > 0) {
            log.info("日志记录成功");
        } else {
            log.error("日志记录失败");
        }
        return rows > 0 ? ResponseResult.builder().build() : ResponseResult.builder().code(ResultCode.SYSTEM_ERROR.getCode()).message(ResultCode.SYSTEM_ERROR.getMessage()).build();
    }
    
    /**
     * 导出住宅列表
     *
     * @param excelRules
     * @return
     */
    @Override
    public ResponseResult occupancyExcel(ExcelRules excelRules) {
        //创建一个目录
        File dir = new File(basePath);
        if(!dir.exists()){
            //目录如果不存在就创建一个
            dir.mkdirs();
        }
        //拿到所有符合入住人数范围的住宅id
        List<String> resids = new ArrayList<>();
        //如果输入了人数区间
        List<Map<String, Object>> maps;
        if (excelRules != null) {
            if (excelRules.getMinNumber() != null && excelRules.getMaxNumber() != null) {
                if(excelRules.getMinNumber() == 0){
                    List<Map<String, Object>> maps1 = residenceDao.countAbodeIdIsNull();
                    for (Map<String, Object> map : maps1) {
                        String abodeId = (String) map.get("abode_id");
                        if(!StringUtils.hasText(abodeId)){//拿到全部为空的住宅id
                            String id = (String) map.get("id");
                            resids.add(id);
                        }
                    }
                }
                //先查询符合条件的住宅id,以及统计对应房屋的人数
                maps = residenceDao.countNumberPersonAbode(excelRules.getMinNumber(), excelRules.getMaxNumber());
                for (Map<String, Object> map : maps) {
                    String id = (String) map.get("id");
                    resids.add(id);
                }
            }
            if(excelRules.getIds() != null){
                List<String> ids = excelRules.getIds();
                ids.addAll(resids);
            }
        }
        //有详细地址
        //特殊处理楼房的详细地址
        String newDetailedAddress2 = null;
        if(excelRules != null && excelRules.getDetailedAddress() != null){
            if(excelRules.getDetailedAddress().size()>1){
                List<String> detailedAddress = excelRules.getDetailedAddress();
                newDetailedAddress2  =  detailedAddress.get(0) +"/"+ detailedAddress.get(1);
            }else{
                List<String> detailedAddress = excelRules.getDetailedAddress();
                newDetailedAddress2 = detailedAddress.get(0);
            }
            excelRules.setAddress(newDetailedAddress2);
        }

        //获取当前登陆人的信息
        User user = (User) ShiroUtils.getSubject().getPrincipal();
        LambdaQueryWrapper<SysUserRole> lambdaQueryWrapper5 = new LambdaQueryWrapper<>();
        lambdaQueryWrapper5.eq(SysUserRole::getUserId, user.getId());
        SysUserRole sysUserRole = sysUserRoleDao.selectOne(lambdaQueryWrapper5);
        String roleKey = sysRoleDao.findByRoles(sysUserRole.getRoleId());
        //如果是街道管理员
        if ("street:admin".equals(roleKey)) {
            assert excelRules != null;
            excelRules.setCommunityIds(null);
        }else {
            //如果是社区管理员
            List<String> commnityIds = sysUserCommunityDao.commnityIds(user.getId());
            if (Objects.isNull(commnityIds) || commnityIds.size() <= 0) {
                return ResponseResult.builder().message("当前用户还没有任何社区权限").build();
            }
            assert excelRules != null;
            excelRules.setCommunityIds(commnityIds);
        }
        List<ExcelRules> excelRulesList = personDao.occFindByIdsExcel(excelRules);
        for (ExcelRules excelRules1 : excelRulesList) {
            //处理业主姓名
            if(StringUtils.hasText(excelRules1.getOwnerId())){
                LambdaQueryWrapper<Person> lambdaQueryWrapper1 = new LambdaQueryWrapper<>();
                lambdaQueryWrapper1.eq(Person::getId,excelRules1.getOwnerId());
                lambdaQueryWrapper1.eq(Person::getEnabled,true);
                Person person = personDao.selectOne(lambdaQueryWrapper1);
                if(Objects.isNull(person)){
                    excelRules1.setPersonName(null);//业主姓名
                }else {
                    excelRules1.setPersonName(person.getName());//业主姓名
                }
            }else{
                excelRules1.setPersonName(null);
            }
            LambdaQueryWrapper<Person> lambdaQueryWrapper = new LambdaQueryWrapper<>();
            lambdaQueryWrapper.eq(Person::getAbodeId, excelRules1.getId());//房屋下的入住人员
            lambdaQueryWrapper.eq(Person::getEnabled,true);
            //处理入住人员姓名
            List<Person> peoples = personDao.selectList(lambdaQueryWrapper);
            StringBuilder stringBuilder = new StringBuilder();
            if (!Objects.isNull(peoples) && peoples.size() > 0) {
                long num = 0L;
                for (Person people : peoples) {
                    if(people != null && StringUtils.hasText(people.getName())){
                        stringBuilder.append(people.getName()).append(" ");
                        num++;
                    }
                }
                excelRules1.setStayPersons(stringBuilder.toString());
                excelRules1.setStayPersonNumber(num);//入住人员数
            } else {
                excelRules1.setStayPersons(null);
                excelRules1.setStayPersonNumber(0L);
            }
        }
        try {
            Date date = new Date();
            SimpleDateFormat simpleDateFormat = new SimpleDateFormat("yyyy-MM-dd HH-mm-ss");
            String format = simpleDateFormat.format(date);
            String filePathName = basePath + format + "入住人员.xlsx";
            EasyExcel.write(filePathName, ExcelRules.class).sheet("入住人员信息").doWrite(excelRulesList);
            return ResponseResult.builder().data(filePathName).build();
        } catch (Exception ex) {
            log.info("写入住人员excel时出现异常！");
            log.info(ex.getMessage());
            return ResponseResult.builder().code(ResultCode.SYSTEM_ERROR.getCode()).message("系统读写文件时，出现异常").build();
        }
    }
    /**
     * excel导出
     * @param filePath
     * @param response
     * @return
     */
    @Override
    public ResponseResult download(String filePath,HttpServletResponse response) {
        //通过输入流，读取文件类容
        try {
            //继续从我们上传保存的位置再次读取这个文件进内存中
            FileInputStream stream = new FileInputStream(new File(filePath));
            //再通过response获取一个输出流，写回给浏览器
            ServletOutputStream outputStream = response.getOutputStream();
            //设置一下响应回去的数据是什么格式
            String fileName = filePath.split("/")[2];
            response.setHeader("Content-Disposition", "attachment;filename=" + URLEncoder.encode(fileName,"UTF-8"));
            byte[] bytes = new byte[1024];
            int len = 0;
            while ((len = stream.read(bytes)) != -1){
                outputStream.write(bytes,0,len);
                outputStream.flush();
            }
            outputStream.close();
            stream.close();
        } catch (Exception e) {
            e.printStackTrace();
        }
        return ResponseResult.builder().build();
    }
}

